#pragma once
#include "../mqcommon/mq_helper.hpp"
#include "../mqcommon/mq_logger.hpp"
#include "../mqcommon/mq_msg.pb.h"
#include <iostream>
#include <memory>
#include <unordered_map>
#include <mutex>
#include <cstring>
#include <functional>
namespace mymq
{
    using ConsumerCallBack = std::function<void(const std::string &, BasicProperties *bp, const std::string &)>;
    struct Consumer
    {
        using Ptr = std::shared_ptr<Consumer>;
        std::string _tag;   // 消费者标识
        std::string _qname; // 订阅的消息队列名字
        bool _auto_ack;     // 是否自动确认
        ConsumerCallBack _callback;
        Consumer(){}
        Consumer(const std::string &tag, const std::string &qname, bool auto_ack, ConsumerCallBack callback)
            : _tag(tag), _qname(qname), _auto_ack(auto_ack), _callback(callback)
        {}
        ~Consumer(){}
    };
    // 以队列为管理单元来对消费者进行管理
    class QueueConsumer
    {
    public:
        using Ptr = std::shared_ptr<QueueConsumer>;
        QueueConsumer(const std::string &qname) : _qname(qname), _rr_seq(0)
        {
        }
        // 新增一个消费者 信道提供的服务是订阅队列消息的时候创建
        Consumer::Ptr Create(const std::string &tag, const std::string &qname, bool auto_ack, ConsumerCallBack callback)
        {
            // 1.加锁
            std::unique_lock<std::mutex> lock(_mutex);
            // 2.判断是否已经存在该消费者
            for (auto &con : _consumers)
            {
                if (con->_tag == tag)
                    return Consumer::Ptr();
            }
            // 3.构造消费者
            Consumer::Ptr con = std::make_shared<Consumer>(tag, qname, auto_ack, callback);
            // 4.添加进管理单元
            _consumers.push_back(con);
            return con;
        }
        // 删除一个消费者 取消订阅 / 信道关闭 / 连接关闭 的时候删除
        bool Remove(const std::string &tag)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            // 找到该消费者进行删除
            for (auto it = _consumers.begin(); it != _consumers.end(); ++it)
            {
                if ((*it)->_tag == tag)
                {
                    _consumers.erase(it);
                    return true;
                }
            }
            return false;
        }
        // 获取消费者：从队列所有的消费者中按序取出一个消费者进行消息的推送
        Consumer::Ptr Choose()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            if (_consumers.size() == 0)
                return Consumer::Ptr();
            int idx = (_rr_seq++) % _consumers.size();
            return _consumers[idx];
        }
        // 判断队列消费者是否为空
        bool Empty()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _consumers.size() == 0;
        }
        // 断指定消费者是否存在
        bool Exists(const std::string &tag)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            for (auto &con : _consumers)
            {
                if (con->_tag == tag)
                    return true;
            }
            return false;
        }
        // 清理队列所有消费者
        void Clear()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _consumers.clear();
            _rr_seq = 0;
        }

    private:
        std::mutex _mutex;
        std::string _qname;
        std::vector<Consumer::Ptr> _consumers;
        uint64_t _rr_seq; // 轮转序号
    };
    class ConsumerManager
    {
    public:
        using Ptr = std::shared_ptr<ConsumerManager>;
        ConsumerManager() {}
        // 初始化队列消费管理单元，在新建队列时初始化
        void InitQueueConsumer(const std::string &qname)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            // 先看看是否已经存在
            auto it = _qconsumers.find(qname);
            if (it != _qconsumers.end())
            {
                return; // 已经存在
            }
            // 不存在
            QueueConsumer::Ptr conmp = std::make_shared<QueueConsumer>(qname);
            _qconsumers.insert(std::make_pair(qname, conmp));
        }
        // 删除队列消费者信息
        void DestoryQueueConsumer(const std::string &qname)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _qconsumers.find(qname);
            if (it == _qconsumers.end())
            {
                return; // 不存在
            }
            _qconsumers.erase(qname);
        }
        // 向指定队列新增一个消费者
        Consumer::Ptr Create(const std::string &ctag, const std::string &qname, bool ack_flag, const ConsumerCallBack &cb)
        {
            QueueConsumer::Ptr conmp;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _qconsumers.find(qname);
                if (it == _qconsumers.end())
                {
                    return Consumer::Ptr(); // 不存在
                }
                conmp = it->second;
            }
            return conmp->Create(ctag, qname, ack_flag, cb);
        }
        // 删除指定队列消费者
        bool Remove(const std::string &tag, const std::string &qname)
        {
            QueueConsumer::Ptr conmp;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _qconsumers.find(qname);
                if (it == _qconsumers.end())
                {
                    return false; // 不存在
                }
                conmp = it->second;
            }
            return conmp->Remove(tag);
        }
        // 移除指定队列的所有消费者（队列被删除时销毁）：删除消费者的队列管理单元对象

        // 从指定队列获取一个消费者
        Consumer::Ptr Choose(const std::string &qname)
        {
            QueueConsumer::Ptr conmp;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _qconsumers.find(qname);
                if (it == _qconsumers.end())
                {
                    return Consumer::Ptr(); // 不存在
                }
                conmp = it->second;
            }
            return conmp->Choose();
        }
        // 判断该队列的消费者是否为空
        bool Empty(const std::string &qname)
        {
            QueueConsumer::Ptr conmp;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _qconsumers.find(qname);
                if (it == _qconsumers.end())
                {
                    DLOG("该队列不存在 %s", qname.c_str());
                    return false; // 不存在
                }
                conmp = it->second;
            }
            conmp->Empty();
        }
        // 判断队列中指定消费者是否存在
        bool Exists(const std::string &tag, const std::string &qname)
        {
            QueueConsumer::Ptr conmp;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _qconsumers.find(qname);
                if (it == _qconsumers.end())
                {
                    DLOG("该队列不存在 %s", qname.c_str());
                    return false; // 不存在
                }
                conmp = it->second;
            }
            return conmp->Exists(tag);
        }
        // 清理所有消费者
        void Clear()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _qconsumers.clear();
        }

    private:
        std::mutex _mutex;
        std::unordered_map<std::string, QueueConsumer::Ptr> _qconsumers; // 对每个队列的消费者进行管理
    };
}